package com.openapi.protocol;

import com.openapi.config.JT808ServerConfig;
import com.openapi.data.JT808PackageData;
import com.openapi.data.JT808PushData;
import com.openapi.protocol.decode.*;
import com.openapi.protocol.decode.subPackageHandle.handle.FileStreamHandle;
import com.openapi.protocol.decode.subPackageHandle.handle.FileUploadFinishedHandle;
import com.openapi.protocol.decode.subPackageHandle.handle.GpsHandle;
import com.openapi.protocol.decode.subPackageHandle.mediaData.MediaDataParse_0801;
import com.openapi.protocol.decode.subPackageHandle.mediaFileList.MediaFileList_0x1205;
import com.openapi.protocol.decode.subPackageHandle.terminalPositionInfoUpload.TerminalPositionInfoUpload_0x0704;
import com.openapi.protocol.encode.Package808;
import com.openapi.service.KafkaService;
import com.openapi.service.LoggerUtil;
import com.openapi.util.RestTemplateUtil;
import exsun.jt808.data.base.MsgDirection;
import exsun.jt808.data.config.jt808.Jt808MsgIdConfig;
import exsun.jt808.data.config.jt808.Jt808MsgIdTopicDic;
import exsun.jt808.data.config.Qingdao.QingdaoMsgIdConfig;
import exsun.jt808.data.distribute_data.jt808.GeneralReply;
import exsun.jt808.data.distribute_data.jt808.TerminalRegisterRsp;
import exsun.jt808.data.kafka_data.KafkaJT808Data;
import exsun.jt808.data.upload_data.*;
import exsun.jt808.data.upload_data.Qingdao.DeviceVersionReporting;
import exsun.jt808.data.upload_data.jsatl12.FileUploadFinished;
import exsun.jt808.data.upload_data.jt808.FileBitStreamLoad;
import exsun.jt808.data.upload_data.jt808.TerminalHearBeat;
import exsun.jt808.data.upload_data.jt808.TerminalParameters;
import exsun.jt808.data.upload_data.jt808.UplinkPassthrough;
import exsun.jt808.data.util.parse.HexStrUtil;
import io.netty.channel.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class ProtocolManager {
    private final static Logger logger = LoggerFactory.getLogger(ProtocolManager.class);

    @Autowired
    private KafkaService kafkaService;

    @Autowired
    private JT808ServerConfig jt808ServerConfig;

    @Autowired
    private  MediaDataParse_0801 mediaDataParse_0801;

    @Autowired
    private TerminalPositionInfoUpload_0x0704 terminalPositionInfoUpload_0x0704;

    @Autowired
    private  MediaFileList_0x1205 mediaFileList_0x1205;

    private static final String authenticationCode = "exsun";

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     *
     * 处理业务逻辑
     *
     * @param packageData
     * @throws Exception
     *
     */
    public Jt808EntityBase handle(JT808PackageData packageData, Channel channel){
        Jt808EntityBase revData = null;
        try {
            int msgId = packageData.getMid();

            List<JT808PushData> jt808PushDatas = new ArrayList<>();
            JT808PushData pushData = null;

            Analyze808 analyze = getAnalyze(packageData.getVersionId());

            switch (msgId){
                //通用应答
                case Jt808MsgIdConfig.TerminalCommonResponse:
                    revData = analyze.terminalCommonResponseDecoder(packageData);
                    dataHandle(packageData,revData);
                    break;
                //终端心跳
                case Jt808MsgIdConfig.TerminalHearBeat:
                    revData = analyze.terminalHearBeatDecoder(packageData);
                    TerminalHearBeat msg = (TerminalHearBeat)revData;
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
                    dataHandle(packageData,revData);
                    //LoggerUtil.logData(msg.dvo,"设备号: " + msg.dvo + "," + "时间:" + sdf.format(msg.pte),"bagData");
                    break;
                //终端注册
                case Jt808MsgIdConfig.terminalRegister:
                    revData = analyze.terminalRegisterDecoder(packageData);
                    TerminalRegisterRsp registerRsp = new TerminalRegisterRsp(packageData.getMsgSerialNo(),0,authenticationCode, packageData.dvo);
                    pushData = Package808.terminalRegisterRsp_0x8100(registerRsp);
                    dataHandle(packageData,revData);
                    break;
                //终端注销
                case Jt808MsgIdConfig.TerminalLogout:
                    revData = analyze.terminalLogoutDecoder(packageData);
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
                    dataHandle(packageData,revData);
                    break;
                //终端鉴权
                case Jt808MsgIdConfig.terminalAuthentication:
                    revData = analyze.terminalAuthenticationDecoder(packageData);
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
                    dataHandle(packageData,revData);
                    break;
                //查询终端参数应答
                case Jt808MsgIdConfig.TerminalQueryParamResponse:
                    revData = analyze.terminalQueryParamResponseDecoder(packageData);
                    dataHandle(packageData,revData);
//                    TerminalParameters parameters = (TerminalParameters)revData;
//                    Map<String,Object> paramMap = new HashMap<>();
//                    paramMap.put("deviceNo",parameters.dvo);
//                    paramMap.put("activeCode",parameters.getActivationCode());
//                    RestTemplateUtil.httpPostForObject(jt808ServerConfig.getActiveCodeUrl(),paramMap);
                    break;
                //查询终端属性应答
                case Jt808MsgIdConfig.TerminalQueryPropResponse:
                    revData = analyze.terminalQueryPropResponseDecoder(packageData);
                    dataHandle(packageData,revData);
                    break;
                //位置信息查询应答
                case Jt808MsgIdConfig.QueryPositionInfoResponse:
                    revData =analyze.QueryPositionInfoDecoder(packageData);
                    dataHandle(packageData,revData);
                    GpsData queryData = (GpsData) revData;
                    Map<String,Object> paramMap = new HashMap<>();
                    paramMap.put("deviceNo",queryData.dvo);
                    paramMap.put("lat",queryData.getLat());
                    paramMap.put("lng",queryData.getLng());
                    RestTemplateUtil.httpPostForObject(jt808ServerConfig.getLocationUrl(),paramMap);
                    break;
                //摄像头立即拍摄指令应答
                case Jt808MsgIdConfig.TakePhotoRightAwayResponse:
                    revData = analyze.takePhotoRightAwayDecoder(packageData);
                    dataHandle(packageData,revData);
                    break;
                //终端升级结果通知
                case Jt808MsgIdConfig.UpgradeResponse:
                    revData = analyze.upgradeResponseDecoder(packageData);
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
                    dataHandle(packageData,revData);
                    break;
                //位置信息汇报
                case Jt808MsgIdConfig.gpsData:
                    revData = analyze.gpsDecoder(packageData);
                    GpsData data = (GpsData)revData;
                    List<JT808PushData> temp1 = GpsHandle.response(data, packageData.dvo);
                    jt808PushDatas.addAll(temp1);
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
//                    data.pop.put(244,"10000000000000000000000000000000");
                    dataHandle(packageData,revData);
                    //logger.info(String.valueOf(data.alm));
                    String msgData = data.GetProperty(GpsPropertyType.ZtWeightValue) + ","
                            + data.gte + "," + sdf.format(data.gdt)
//                            + (data.sts.contains(GpsStatusType.FrontDoor)?"1":"0") + ","
//                            + data.spd + ","
//                            + (data.sts.contains(GpsStatusType.Acc)?"1":"0") + ","
//                            + data.mie
                            ;
                    if (data.GetProperty(GpsPropertyType.ZtWeightValue) == null && data.dvo.equals("020210406077")){
                        LoggerUtil.logData(data.dvo, msgData,"loadNull");
                    }else if (data.GetProperty(GpsPropertyType.ZtWeightValue) != null && data.dvo.equals("020210406077")){
                        LoggerUtil.logData(data.dvo, msgData,"loadNoNull");
                    }

                    break;
                //事件报告
                case Jt808MsgIdConfig.EventUpload:
                    revData = analyze.eventUploadDecoder(packageData);
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
                    dataHandle(packageData,revData);
                    break;
                //车辆控制应答
                case Jt808MsgIdConfig.VehicleControlResponse:
                    revData = analyze.vehicleControlResponseDecoder(packageData);
                    dataHandle(packageData,revData);
                    break;
                //行驶记录数据上传
                case Jt808MsgIdConfig.CollectDataResponse:
                    revData = analyze.collectDataDecoder(packageData);
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
                    dataHandle(packageData,revData);
                    break;
                //电子运单上报
                case Jt808MsgIdConfig.ElectronicWaybill:
                    revData = analyze.electronicWaybillDecoder(packageData);
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
                    dataHandle(packageData,revData);
                    break;
                //驾驶员身份信息采集上报
                case Jt808MsgIdConfig.DriverInfoUploadResponse:
                    revData = analyze.driverInfoUploadDecoder(packageData);
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
                    dataHandle(packageData,revData);
                    break;
                //CAN 总线数据上传
                case Jt808MsgIdConfig.CANData:
                    revData = analyze.CANDataDecoder(packageData);
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
                    dataHandle(packageData,revData);
                    break;
                //多媒体事件信息上传
                case Jt808MsgIdConfig.MediaEvent:
                    revData = analyze.mediaEventDecoder(packageData);
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
                    dataHandle(packageData,revData);
                    break;
                //多媒体数据上传
                case Jt808MsgIdConfig.mediaData:
                    List<JT808PushData> temp2  = mediaDataParse_0801.decode(packageData);
                    jt808PushDatas.addAll(temp2);
                    dataHandle(packageData,revData);
                    break;
                //存储多媒体数据检索应答
                case Jt808MsgIdConfig.MediaQueryResponse:
                    revData = analyze.mediaDataDecoder(packageData);
                    dataHandle(packageData,revData);
                    break;
                //1078终端上传音视频资源列表
                case Jt808MsgIdConfig.mediaFileList:
                    pushData = mediaFileList_0x1205.decode(packageData);
                    dataHandle(packageData,revData);
                    break;
                //报警附件信息消息
                case Jt808MsgIdConfig.alarmAttachmentInfo:
                    revData = AnalyzeHj212.alarmAttachmentInfoDecoder(packageData);
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
                    dataHandle(packageData,revData);
                    break;
                //文件信息上传
                case Jt808MsgIdConfig.fileInfoUpload:
                    revData = AnalyzeHj212.fileInfoUploadDecoder(packageData);
                    pushData = Package808.generalReply_0x8001(new GeneralReply(packageData,0));
                    dataHandle(packageData,revData);
                    break;
                //文件数据上传
                case Jt808MsgIdConfig.jsalt12FileMsgId:
                    revData = AnalyzeHj212.fileStreamDecoder(packageData);
                    FileStreamHandle.response((FileBitStreamLoad)revData, packageData.dvo);
                    dataHandle(packageData,revData);
                    break;
                //文件上传完成消息
                case Jt808MsgIdConfig.fileUploadFinished:
                    revData = AnalyzeHj212.fileUploadFinishedDecoder(packageData);
                    List<JT808PushData> temp4 = FileUploadFinishedHandle.response((FileUploadFinished)revData, packageData.dvo);
                    jt808PushDatas.addAll(temp4);
                    dataHandle(packageData,revData);
                    break;
                //定位信息批量上传
                case Jt808MsgIdConfig.TerminalPositionInfoUpload_0x0704:
                    pushData = terminalPositionInfoUpload_0x0704.decode(packageData);
                    dataHandle(packageData,revData);
                    break;
                //数据上行透传
                case Jt808MsgIdConfig.DataUpTransmission:
                    revData = analyze.uplinkPassThroughDecoder(packageData);
                    UplinkPassthrough passData = (UplinkPassthrough)revData;
                    dataHandle(packageData,revData);
                    if (passData.getMsgType() == 0x00){
                        LoggerUtil.logData(passData.dvo,"GNSS数据:" + passData.getContent(),"GNSSData");
                    }
//                    else if (passData.getMsgType() == 0x41){
//                        passData.setPmTwoPointFive(HexStrUtil.HexToInt(String.valueOf(passData.getPmTwoPointFive())));
//                        passData.setPmTen(HexStrUtil.HexToInt(String.valueOf(passData.getPmTen())));
//                    }
                    break;
                /**
                 * 智能终端协议
                 */
                //管控开关状态应答
                case QingdaoMsgIdConfig.controlSwitchResponse:
                    revData = AnalyzeQingdao.ControlSwitchResponse(packageData);
                    dataHandle(packageData,revData);
                    break;
                //管控开关查询的应答
                case QingdaoMsgIdConfig.controlSwitchSortResponse:
                    revData = AnalyzeQingdao.ControlSwitchSortResponse(packageData);
                    dataHandle(packageData,revData);
                    break;
                //查询多边形区域的应答
                case QingdaoMsgIdConfig.sortPolygonAreaResponse:
                    revData = AnalyzeQingdao.SortPolygonAreaResponse(packageData);
                    dataHandle(packageData,revData);
                    break;
                //查询线路的应答
                case QingdaoMsgIdConfig.sortRouteResponse:
                    revData = AnalyzeQingdao.SortRouteResponse(packageData);
                    dataHandle(packageData,revData);
                    break;
                //驾驶员图片下载应答
                case QingdaoMsgIdConfig.driverPictureDownLoadResponse:
                    revData = AnalyzeQingdao.driverPictureDownLoad(packageData);
                    dataHandle(packageData,revData);
                    break;
                //驾驶员图片信息应答
                case QingdaoMsgIdConfig.driverPictureMsgResponse:
                    revData = AnalyzeQingdao.driverPictureMsgResponse(packageData);
                    dataHandle(packageData,revData);
                    break;
                //驾驶员对比结果上报应答
                case QingdaoMsgIdConfig.driverContrastResultResponse:
                    List<JT808PushData> temp3 = AnalyzeQingdao.driverContrastResultDecoder(packageData);
                    jt808PushDatas.addAll(temp3);
                    dataHandle(packageData,revData);
                    break;
                //设备录入驾驶员信息上报平台应答
                case Jt808MsgIdConfig.DeviceInputResponse:
                    List<JT808PushData> temp5 = AnalyzeQingdao.deviceInputResponseDecoder(packageData);
                    jt808PushDatas.addAll(temp5);
                    dataHandle(packageData,revData);
                    break;
                //升级完成应答
                case  Jt808MsgIdConfig.UpgradeCompleteResopnse:
                    revData = AnalyzeQingdao.upgradeCompleteResponseDecoder(packageData);
                    dataHandle(packageData,revData);
                    break;
                //设备版本上报
                case Jt808MsgIdConfig.DeviceVersionReporting:
                    revData = AnalyzeQingdao.deviceVersionReporting(packageData);
                    dataHandle(packageData,revData);
                    DeviceVersionReporting deviceVersionReporting = (DeviceVersionReporting) revData ;
                    Map<String,Object> deviceMap = new HashMap<>();
                    deviceMap.put("deviceNo",deviceVersionReporting.dvo);
                    deviceMap.put("versionNumber",deviceVersionReporting.getVersionNumber());
                    RestTemplateUtil.httpPostForObject(jt808ServerConfig.getDeviceVersionUrl(),deviceMap);
                    break;
                //查询区域或线路数据
                case Jt808MsgIdConfig.QueryAreaOrLineDataResponse:
                    revData = ((Analyze8082019)analyze).queryAreaOrLineDataResponseDecoder(packageData);
                    dataHandle(packageData,revData);
                    break;
                //查询服务器时间应答
                case Jt808MsgIdConfig.QueryServerTimeRequest:
                    revData = ((Analyze8082019)analyze).queryServerTimeRequestDecoder(packageData);
                    dataHandle(packageData,revData);
                    break;
                //农机自动标定应答
                case Jt808MsgIdConfig.AutoCalibrationResponse:
                    revData = analyze.AutoCalibrationResponse(packageData);
                    dataHandle(packageData,revData);
                    break;
                //文件上传完成应答
                case Jt808MsgIdConfig.fileUploadResponse:
                    revData = Analyze1078.fileUploadResponse(packageData);
                    dataHandle(packageData,revData);
                    break;
                default:
                    break;
            }
            if(pushData != null){jt808PushDatas.add(pushData);}
            jt808PushDatas.forEach(item->{
                channel.writeAndFlush(item);
            });

        }catch (Exception e){
            logger.error("数据处理异常：{},{},{},{}",packageData.tpc,packageData.dvo,packageData.getMid(),  e.getMessage());
        }finally {
            return revData;
        }
    }

    private Analyze808 getAnalyze(Integer version){
        Analyze808 analyz = null;
        if(version == null|| version == 0){
            analyz = new Analyze808();
        }else{
            analyz = new Analyze8082019();
        }
        return analyz;
    }

    private void dataHandle(JT808PackageData packageData, Jt808EntityBase revData){
        if(revData != null){
            revData.mid = packageData.getMid();
            revData.messageLength = packageData.getMessageLength();
            revData.encryption = packageData.getEncryption();
            revData.subcontracting = packageData.getSubcontracting();
            revData.media = packageData.getMedia();
            revData.dvo = packageData.getDvo();
            revData.msgSerialNo = packageData.getMsgSerialNo();
            revData.packageSize = packageData.getPackageSize();
            revData.packageIndex = packageData.getPackageIndex();
            revData.pte = packageData.getPte();
            revData.tpc = Jt808MsgIdTopicDic.getMsgTopic(packageData.getMid());
        }
    }



    /**
     * 推送解析后的数据
     * @param data
     */
    public void tMQ(Jt808EntityBase data)
    {
        int port = jt808ServerConfig.getJt808ServerPort();
        KafkaJT808Data kafkaJT808Data = new KafkaJT808Data(data,data.dvo,data.mid,data.tpc, MsgDirection.up, port);
        String sendData = kafkaJT808Data.getJsonFromObject();
        kafkaService.push(data.tpc, kafkaJT808Data.getDevNo(), sendData);


//        logger.info(sendData);

    }
}
